package cn.rxyb.core.respone;

import cn.rxyb.core.respone.enums.CommonCode;
import cn.rxyb.core.respone.exception.RException;
import lombok.Data;

import java.io.Serializable;
import java.util.Optional;

/**
 * @author YJH
 * @version 1.0
 * @description 统一响应
 * @date 2020/5/21  11:35
 */
@Data
public final class R<T> implements Serializable {

    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 1L;

    /**
     * 业务错误码
     */
    private String code;
    /**
     * 结果集
     */
    private T data;
    /**
     * 描述
     */
    private String msg;

    public R() {
        // to do nothing
    }

    /**
     * 构造函数
     *
     * @param errorCode 响应码得统一结合<>br</>
     */
    public R(IBaseCode errorCode) {
        errorCode = Optional.ofNullable(errorCode).orElse(CommonCode.FAILED);
        this.code = errorCode.getCode();
        this.msg = errorCode.getMsg();
    }

    /**
     * 成功响应结果参数 </br>
     *
     * @param data 返回得业务接口 </br>
     * @param <T>  响应类型 <br/>
     * @return
     */
    public static <T> R<T> ok(T data) {
        CommonCode aec = CommonCode.SUCCESS;
        if (data instanceof Boolean && Boolean.FALSE.equals(data)) {
            aec = CommonCode.FAILED;
        }
        return restResult(data, aec);
    }

    /**
     * 失败时,响应码统一返回,描述可定义 <br/>
     *
     * @param msg 自定义描述信息 <br/>
     * @param <T> 响应类型 <br/>
     * @return
     */
    public static <T> R<T> failed(String msg) {
        return restResult(null, CommonCode.FAILED.getCode(), msg);
    }

    /**
     * 失败时,通过自定义响应信息返回<>br</>
     *
     * @param errorCode 自定义枚举响应码信息, 需要实现 IErrorCode接口 <>br</>
     * @param <T>       响应类型 <br/>
     * @return
     */
    public static <T> R<T> failed(IBaseCode errorCode) {
        return restResult(null, errorCode);
    }

    /**
     * 自定义业务参数、响应信息返回<>br</>
     *
     * @param data      业务参数<>br</>
     * @param errorCode 自定义枚举响应码信息, 需要实现 IErrorCode接口 <>br</>
     * @param <T>       响应类型<>br</>
     * @return
     */
    public static <T> R<T> restResult(T data, IBaseCode errorCode) {
        return restResult(data, errorCode.getCode(), errorCode.getMsg());
    }

    /**
     * 自定义业务参数、响应信息返回<>br</>
     *
     * @param data 业务参数<>br</>
     * @param code 自定义响应码<>br</>
     * @param msg  自定义响描述<>br</>
     * @param <T>  响应类型<>br</>
     * @return
     */
    private static <T> R<T> restResult(T data, String code, String msg) {
        R<T> apiResult = new R<>();
        apiResult.setCode(code);
        apiResult.setData(data);
        apiResult.setMsg(msg);
        return apiResult;
    }

    /**
     * 判断R<T>结果是否成功
     *
     * @return
     */
    public boolean ok() {
        return CommonCode.SUCCESS.getCode().equals(code);
    }

    /**
     * 服务间调用非业务正常，异常直接释放
     */
    public T serviceData() {
        if (!ok()) {
            throw new RException(this.msg);
        }
        return data;
    }

}
